﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SocketServerCSharp
{
    public class ServerMgr //: ISocketServer
    {
        private AsyncTcpServer _tcpServer = null;
        private string _localIp = "127.0.0.1";
        private int _port = 888;

        private Thread recvDataThrd = null;
        CancellationTokenSource recvDataCts = null;
        object recvObj = new object();
        public Queue<ComData> comDataQueue = new Queue<ComData>();
        public int comDQLength = 100; //指令集队列长度上限

        #region 构造器
        public ServerMgr()
            : this("127.0.0.1", 888)
        {
        }

        public ServerMgr(string ip, int port)
        {
            _localIp = ip;
            _port = port;
        }
        #endregion

        public bool open()
        {
            try
            {
                //开启服务器
                _tcpServer = new AsyncTcpServer(_localIp, _port, (new ComData()).GetType())
                {
                    Encoding = Encoding.UTF8
                };
                _tcpServer.ClientConnected +=
                              new EventHandler<TcpClientConnectedEventArgs>(Server_ClientConnected);
                _tcpServer.ClientDisconnected +=
                  new EventHandler<TcpClientDisconnectedEventArgs>(Server_ClientDisconnected);

                _tcpServer.Start();
                _tcpServer.OnReceiveData += TcpServer_OnReceiveData;

                //启动侦听线程
                recvDataCts = new CancellationTokenSource();
                recvDataThrd = new Thread(new ThreadStart(RecvDataFunc))
                {
                    IsBackground = true
                };
                recvDataThrd.Start();
                var msg = string.Format("服务已开启({0}:{1})，等待主机客户端连接", _localIp, _port);
                Console.WriteLine(msg);
                return true;
            }
            catch (Exception ex)
            {
                var msg = string.Format("从机未开机，请开启运动控制电脑，并检查网络连接\n{0}", ex.Message);
                Console.WriteLine(ex.Message);
                return false;
            }
        }

        private void TcpServer_OnReceiveData(ComData data)
        {
            comDataQueue.Enqueue(data);
        }

        void Server_ClientConnected(object sender, TcpClientConnectedEventArgs e)
        {
            var msg = string.Format("客户端已连接{0}", e.TcpClient.Client.RemoteEndPoint.ToString());
            Console.WriteLine(msg);
        }

        void Server_ClientDisconnected(object sender, TcpClientDisconnectedEventArgs e)
        {
            var msg = string.Format("客户端已断开连接{0}", e.TcpClient.Client.RemoteEndPoint.ToString());
            Console.WriteLine(msg);
        }


        public void close()
        {
            //关闭侦听线程
            this.recvDataCts.Cancel();

            //关闭服务器
            //this._tcpServer.CloseAll();
            this._tcpServer.Dispose();

            //清空数据缓存
            this.comDataQueue.Clear();
        }


        //指令集解析线程
        private void RecvDataFunc()
        {
            try
            {
                while (true)
                {
                    if (recvDataCts.Token.IsCancellationRequested)
                        return;

                    //线程锁
                    lock (recvObj)
                    {
                        if (comDataQueue.Count < 1)
                        {
                            Thread.Sleep(10);
                            continue;
                        }
                    }

                    //查询指令队列对首
                    ComData _comData = comDataQueue.Peek();
                    var cmdID = _comData.cmdID;
                    switch (cmdID)
                    {
                        case 5://开始检测
                            Function_0005(_comData);
                            break;
                        default:
                            break;
                    }
                    if (comDataQueue.Count > 0)
                        comDataQueue.Dequeue();
                    Thread.Sleep(50);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error" + ex.Message);
            }
        }

        private void Function_0005(ComData _comData)
        {
            /*
            Console.WriteLine($"收到Authentic为:{Encoding.ASCII.GetString(_comData.Authentic)}");
            Console.WriteLine($"收到Reserve为:{Encoding.ASCII.GetString(_comData.Reserve)}");
            Console.WriteLine($"收到AddIn为:{Encoding.ASCII.GetString(_comData.AddIn)}");*/
            Console.WriteLine($"收到ID为:{(new string(_comData.cData)).TrimEnd('\0')}");
            Console.WriteLine("****************************************************");
            ComData _resultData = new ComData(3);
            _resultData.iData[0] = 1;
            _resultData.result = 1;
            _resultData.dData[0] = 3.012;
            var msg = "A123456789QWERTYUIOP987654321";
            Console.WriteLine($"发送ID为:{msg}");
            _resultData.cData = msg.PadRight(256, '\0').ToCharArray();
            _tcpServer.SendMessage(_resultData);
        }

        public static string CharToString(char[] chars)
        {
            string str = "";
            int len = 0;
            for (int i = 0; i < chars.Length; i++)
            {
                if (chars[i] == '\0')
                {
                    len = i;
                    break;
                }
            }
            string msg = new string(chars);
            str = msg.Substring(0, len);
            return str;
        }

        /// <summary>
        /// 将列表中的数据通过-号连接，并返回连接后的字符串
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="lst"></param>
        /// <returns></returns>
        public static string GetString<T>(List<T> lst)
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < lst.Count; i++)
            {
                sb.Append(lst[i]);
                if (i < lst.Count - 1)
                    sb.Append("-");
            }
            return sb.ToString();
        }

        public async Task<bool> Init()
        {
            var task = Task.Factory.StartNew(open, TaskCreationOptions.AttachedToParent);
            await task;
            return task.Result;
        }
    }
}
